#include "SocketMgrLinux.h"

#include "Socket.h"
#include "ListenSocketLinux.h"

SocketMgr::SocketMgr()
{
    m_pkCall = NULL;
}
SocketMgr::~SocketMgr()
{
    close(m_iEpollFd);
}

bool SocketMgr::Init()
{
    m_iEpollFd = epoll_create(SOCKET_HOLDER_SIZE);
    if(m_iEpollFd == -1)
    {
        printf("Could not create epoll fd (/dev/epoll).");
        return false;
    }
    return true;
}

void SocketMgr::Update()
{
    m_kFdMutex.Acquire();
    std::map<SOCKET,Socket*>::iterator it = m_kFdMap.begin();
    //printf("==================SocketMgr::Update()==================.\n");
    //printf("==================m_kFdMap Size:[%d]===================.\n",m_kFdMap.size());
    //printf("==================SocketMgr::Update()==================.\n");
    for(;it != m_kFdMap.end();it++)
    {
        Socket* s = it->second;
        if(s && s->IsConnected())
        {
            char buf[1024] = {};
            int  iSize = 0;
            s->OnRead(buf,iSize);
            if(iSize != 0)
            {
                GetCall()->OnRecv(s->GetFd(),buf,iSize);
            }
            //s->PostEvent(EPOLLOUT);
            if(!s->WriteCallback())
            {
               DisConnect(s);
            }
        }
    }
    m_kFdMutex.Release();
}
Socket* SocketMgr::CreateSocket(SOCKET sSocket,int iSendBufferSize,int iRecvBufferSize)
{
    return new Socket(sSocket,iSendBufferSize,iRecvBufferSize);
}


void SocketMgr::AddSocket(Socket* s)
{
    if(s->GetFd() > 1200)
    {
        printf("SocketMgr::AddSocket Error.\n");
        exit(1);
    }

    struct epoll_event ev;
    memset(&ev, 0, sizeof(epoll_event));
    ev.events =  EPOLLIN | EPOLLET | EPOLLERR | EPOLLHUP | EPOLLPRI;
    ev.data.ptr = s;
    if(epoll_ctl(m_iEpollFd,EPOLL_CTL_ADD,s->GetFd(),&ev))
    {
        printf("epoll", "Could not add event to epoll set on fd %u",s->GetFd());
    }
    m_kFdMutex.Acquire();
    m_kFdMap[s->GetFd()] = s;
    m_kFdMutex.Release();
    printf("SocketMgr::AddSocket[%llu][%d].\n",s,s->GetFd());
}

void SocketMgr::RemoveSocket(Socket* s)
{
    m_kFdMutex.Acquire();
    std::map<SOCKET,Socket*>::iterator it = m_kFdMap.find(s->GetFd());
    if(it == m_kFdMap.end())
    {
        m_kFdMutex.Release();
        return;
    }
    m_kFdMap.erase(it);
    m_kFdMutex.Release();

    struct epoll_event ev;
    memset(&ev, 0, sizeof(epoll_event));
    ev.events = EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP | EPOLLONESHOT;
    //ev.events = EPOLLERR | EPOLLHUP | EPOLLET;
    ev.data.ptr = s;
    if(epoll_ctl(m_iEpollFd, EPOLL_CTL_DEL,s->GetFd(),&ev))
    {
        printf("epoll", "Could not remove fd %u from epoll set, errno %u", s->GetFd(), errno);
    }
    printf("SocketMgr::RemoveSocket[%d].\n",s->GetFd());
}
int SocketMgr::GetSocketCount()
{
    m_kFdMutex.Acquire();
    int iCount = m_kFdMap.size();
    m_kFdMutex.Release();
    return iCount;
}

Socket* SocketMgr::ConnectTCPSocket(const char * pcHostName,int iPort,int iSendBufferSize,int iRecvBufferSize)
{
    sockaddr_in kConn;
    struct hostent* pkHost = gethostbyname(pcHostName);
    if(!pkHost)
    {
        return NULL;
    }

    memcpy(&kConn.sin_addr, pkHost->h_addr_list[0], sizeof(in_addr));
    kConn.sin_family = AF_INET;
    kConn.sin_port = ntohs(iPort);

    Socket* s = CreateSocket(1,iSendBufferSize,iRecvBufferSize);
    s->SetServerAddr(kConn);
    if(!s->Connect(pcHostName, iPort))
    {
        return NULL;
    }
    AddSocket(s);
    GetCall()->OnConnected(0,"192.168.0.1",1314);
    return s;	
}

void SocketMgr::DisConnect(SOCKET sFd)
{
    m_kFdMutex.Acquire();
    Socket* s = m_kFdMap[sFd];
    m_kFdMutex.Release();
    if(s)
    {
        DisConnect(s);
    }
}
void SocketMgr::DisConnect(Socket* s)
{
    GetCall()->OnDisConnect(s->GetFd());
    RemoveSocket(s);
    s->DisConnect();
    delete s;
}
void SocketMgr::CloseAll()
{
    std::map<SOCKET,Socket*>::iterator it = m_kFdMap.begin();
    for(;it != m_kFdMap.end();it++)
    {
        Socket* s = (Socket*)it->second;
        if(s)
        {
            DisConnect(s);
        }
    }
}
bool SocketMgr::SendBuffer(SOCKET sFd,void* pData,int iSize)
{
    m_kFdMutex.Acquire();
    Socket* s = m_kFdMap[sFd];
    m_kFdMutex.Release();
    if(s)
    {
        s->Send((const uint8*)pData,iSize);
    }
}

void SocketMgr::Run()
{
    printf("Socket R/W Thread Run....................................\n");
    while(Active())
    {
        int iFdCount = epoll_wait(m_iEpollFd,m_kEvents,THREAD_EVENT_SIZE,5000);
        for(int i = 0; i < iFdCount; ++i)
        {
            Socket* pkPtr = (Socket*)m_kEvents[i].data.ptr;
            if(!pkPtr)
            {
                printf("SocketWorkerThread::Run() Can`t Find FD.\n");
                continue;
            }
 
            if(m_kEvents[i].events & EPOLLHUP || m_kEvents[i].events & EPOLLERR)
            {
                printf("SocketWorkerThread::Run() DisConect().");
                DisConnect(pkPtr);
                continue;
            }
            else if(m_kEvents[i].events & EPOLLIN)
            {
                if(!pkPtr->ReadCallback(0))
                {
                    DisConnect(pkPtr);
                }
            }
            /*else if(m_kEvents[i].events & EPOLLOUT)
            {
                pkPtr->WriteCallback();
                pkPtr->PostEvent(EPOLLIN);
                                    
            }*/
        }       
    }
}

